﻿using System;
using System.ComponentModel;
using System.Data.Linq;
using System.Data.Linq.Mapping;

namespace Yuanna.Model
{
    public class YuannaDataContext : DataContext
    {
        public YuannaDataContext()
            : base("Data Source=isostore:/Yuanna.sdf")
        { }

        public Table<YuannaPoint> Points;

        public Table<YuannaPath> Paths;
    }

    /// <summary>
    /// 坐标点表，副表
    /// </summary>
    [Table]
    public class YuannaPoint : INotifyPropertyChanged, INotifyPropertyChanging
    {
        /// <summary>
        /// 实体ID
        /// </summary>
        private int _id;

        /// <summary>
        /// 实体ID
        /// </summary>
        [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
        public int Id
        {
            get { return _id; }
            set
            {
                if (_id != value)
                {
                    NotifyPropertyChanging("Id");
                    _id = value;
                    NotifyPropertyChanged("Id");
                }
            }
        }

        /// <summary>
        /// 经度
        /// </summary>
        private double _longitude;

        /// <summary>
        /// 经度
        /// </summary>
        [Column]
        public double Longitude
        {
            get { return _longitude; }
            set
            {
                if (_longitude != value)
                {
                    NotifyPropertyChanging("Longitude");
                    _longitude = value;
                    NotifyPropertyChanged("Longitude");
                }
            }
        }

        /// <summary>
        /// 纬度
        /// </summary>
        private double _latitude;

        /// <summary>
        /// 纬度
        /// </summary>
        [Column]
        public double Latitude
        {
            get { return _latitude; }
            set
            {
                if (_latitude != value)
                {
                    NotifyPropertyChanging("Latitude");
                    _latitude = value;
                    NotifyPropertyChanged("Latitude");
                }
            }
        }

        /// <summary>
        /// 即时速度
        /// </summary>
        private double _speed = 0;

        /// <summary>
        /// 即时速度
        /// </summary>
        [Column]
        public double Speed
        {
            get { return _speed; }
            set
            {
                if (_speed != value)
                {
                    NotifyPropertyChanging("Speed");
                    _speed = value;
                    NotifyPropertyChanged("Speed");
                }
            }
        }

        /// <summary>
        /// 创建时间
        /// </summary>
        private DateTime _createtime;

        /// <summary>
        /// 创建时间
        /// </summary>
        [Column]
        public DateTime CreateTime
        {
            get { return _createtime; }
            set
            {
                if (_createtime != value)
                {
                    NotifyPropertyChanging("CreateTime");
                    _createtime = value;
                    NotifyPropertyChanged("CreateTime");
                }
            }
        }

        // Version column aids update performance.
        [Column(IsVersion = true)]
        private Binary _version;

        /// <summary>
        /// 一对多，对应所属的路径
        /// </summary>
        [Column]
        internal int _pathid;
        private EntityRef<YuannaPath> _path;

        /// <summary>
        /// 构造器，与父实体建立关系
        /// </summary>
        [Association(Storage = "_path", ThisKey = "_pathid", OtherKey = "Id", IsForeignKey = true)]
        public YuannaPath Path
        {
            get { return _path.Entity; }
            set
            {
                NotifyPropertyChanging("Path");
                _path.Entity = value;

                if (value != null)
                {
                    _pathid = value.Id;
                }

                NotifyPropertyChanging("Path");
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        // Used to notify that a property changed
        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

        #region INotifyPropertyChanging Members

        public event PropertyChangingEventHandler PropertyChanging;

        // Used to notify that a property is about to change
        private void NotifyPropertyChanging(string propertyName)
        {
            if (PropertyChanging != null)
            {
                PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
            }
        }

        #endregion
    }

    /// <summary>
    /// 路径表，主表
    /// </summary>
    [Table]
    public class YuannaPath : INotifyPropertyChanged, INotifyPropertyChanging
    {
        /// <summary>
        /// 是否正在追踪，无需保存在数据库中，仅用来高亮标识当前正在追踪的路径项
        /// </summary>
        private bool _isTracking = false;

        /// <summary>
        /// 是否正在追踪，无需保存在数据库中，仅用来高亮标识当前正在追踪的路径项
        /// </summary>
        public bool IsTracking
        {
            get
            {
                return _isTracking;
            }
            set
            {
                _isTracking = value;
            }
        }

        /// <summary>
        /// 实体ID
        /// </summary>
        private int _id;

        /// <summary>
        /// 实体ID
        /// </summary>
        [Column(DbType = "INT NOT NULL IDENTITY", IsDbGenerated = true, IsPrimaryKey = true)]
        public int Id
        {
            get { return _id; }
            set
            {
                if (_id != value)
                {
                    NotifyPropertyChanging("Id");
                    _id = value;
                    NotifyPropertyChanged("Id");
                }
            }
        }

        /// <summary>
        /// 距离
        /// </summary>
        private double _distance = 0;

        /// <summary>
        /// 距离
        /// </summary>
        [Column]
        public double Distance
        {
            get { return _distance; }
            set
            {
                if (_distance != value)
                {
                    NotifyPropertyChanging("Distance");
                    _distance = value;
                    NotifyPropertyChanged("Distance");
                }
            }
        }

        /// <summary>
        /// 速度(千米每小时)
        /// </summary>
        private double _speed = 0;

        /// <summary>
        /// 速度(千米每小时)
        /// </summary>
        [Column]
        public double Speed
        {
            get { return _speed; }
            set
            {
                if (_speed != value)
                {
                    NotifyPropertyChanging("Speed");
                    _speed = value;
                    NotifyPropertyChanged("Speed");
                }
            }
        }

        /// <summary>
        /// 花费时间
        /// </summary>
        private string _duration = new TimeSpan(0, 0, 0).ToString();

        /// <summary>
        /// 花费时间
        /// </summary>
        [Column]
        public string Duration
        {
            get { return _duration; }
            set
            {
                if (_duration != value)
                {
                    NotifyPropertyChanging("Duration");
                    _duration = value;
                    NotifyPropertyChanged("Duration");
                }
            }
        }

        /// <summary>
        /// 跑步热量（kcal）＝体重（kg）×距离（公里）×1.036
        /// </summary>
        public double Calorie
        {
            get
            {
                var weight = 65; // 默认为65KG
                return weight * Distance * 1.036;
            }
        }

        /// <summary>
        /// 计算平均速度
        /// </summary>
        public void GetAverageSpeed()
        {
            TimeSpan time = TimeSpan.Zero;
            TimeSpan.TryParse(Duration, out time);
            var totalHours = time.TotalHours;
            if (totalHours == 0)
            {
                Speed = 0;
            }
            else
            {
                Speed = Distance / TimeSpan.Parse(Duration).TotalHours;
            }
        }


        /// <summary>
        /// 创建时间
        /// </summary>
        private DateTime _createtime;

        /// <summary>
        /// 创建时间
        /// </summary>
        [Column]
        public DateTime CreateTime
        {
            get { return _createtime; }
            set
            {
                if (_createtime != value)
                {
                    NotifyPropertyChanging("CreateTime");
                    _createtime = value;
                    NotifyPropertyChanged("CreateTime");
                }
            }
        }

        /// <summary>
        /// 是否已同步
        /// </summary>
        private bool _issync;

        /// <summary>
        /// 是否已同步
        /// </summary>
        [Column]
        public bool IsSync
        {
            get { return _issync; }
            set
            {
                if (_issync != value)
                {
                    NotifyPropertyChanging("IsSync");
                    _issync = value;
                    NotifyPropertyChanged("IsSync");
                }
            }
        }

        /// <summary>
        /// 是否标记为删除
        /// </summary>
        private bool _isdelete;

        /// <summary>
        /// 是否标记为删除
        /// </summary>
        [Column]
        public bool IsDelete
        {
            get { return _isdelete; }
            set
            {
                if (_isdelete != value)
                {
                    NotifyPropertyChanging("IsDelete");
                    _isdelete = value;
                    NotifyPropertyChanged("IsDelete");
                }
            }
        }

        // Version column aids update performance.
        [Column(IsVersion = true)]
        private Binary _version;


        /// <summary>
        /// 一对多，对应一个坐标点集合
        /// </summary>
        private EntitySet<YuannaPoint> _points;

        [Association(Storage = "_points", OtherKey = "_pathid", ThisKey = "Id")]
        public EntitySet<YuannaPoint> Points
        {
            get { return this._points; }
            set { this._points.Assign(value); }
        }

        /// <summary>
        /// 构造器
        /// </summary>
        public YuannaPath()
        {
            _points = new EntitySet<YuannaPoint>(
                new Action<YuannaPoint>(this.attach_Point),
                new Action<YuannaPoint>(this.detach_Point)
                );
        }

        // Called during an add operation
        private void attach_Point(YuannaPoint point)
        {
            NotifyPropertyChanging("Points");
            point.Path = this;
        }

        // Called during a remove operation
        private void detach_Point(YuannaPoint point)
        {
            NotifyPropertyChanging("Points");
            point.Path = null;
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        // Used to notify that a property changed
        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

        #region INotifyPropertyChanging Members

        public event PropertyChangingEventHandler PropertyChanging;

        // Used to notify that a property is about to change
        private void NotifyPropertyChanging(string propertyName)
        {
            if (PropertyChanging != null)
            {
                PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
            }
        }

        #endregion
    }
}
